﻿import 'package:easy_refresh/easy_refresh.dart';
import 'package:flutter/material.dart';

import 'models.dart';
import 'refreshable_list_controller.dart';

class RefreshableList<T> extends StatefulWidget {
  const RefreshableList({
    super.key,
    required this.fetchData,
    required this.itemBuilder,
    required this.controller,
    this.pageSize = 10,
    this.initialPage = 1,
    this.emptyWidget,
    this.loadingWidget,
    this.header,
    this.footer,
    this.scrollController,
    this.onError,
  });

  final Future<ListResponse<T>> Function(int page, int pageSize) fetchData;
  final Widget Function(T item) itemBuilder;
  final RefreshableListController controller;

  final int pageSize;
  final int initialPage;
  final Widget? emptyWidget;
  final Widget? loadingWidget;
  final Header? header;
  final Footer? footer;
  final ScrollController? scrollController;
  final void Function(Object error, StackTrace stackTrace)? onError;

  @override
  State<RefreshableList<T>> createState() => _RefreshableListState<T>();
}

class _RefreshableListState<T> extends State<RefreshableList<T>> {
  final List<T> _items = <T>[];
  late EasyRefreshController _easyRefreshController;
  ScrollController? _internalScrollController;

  int _total = 0;
  late int _page;
  bool _refreshing = false;
  bool _loadingMore = false;

  ScrollController get _effectiveScrollController =>
      widget.scrollController ?? _internalScrollController!;

  bool get _hasMore => _items.length < _total;

  @override
  void initState() {
    super.initState();
    _page = widget.initialPage;
    _easyRefreshController = EasyRefreshController(
      controlFinishRefresh: true,
      controlFinishLoad: true,
    );
    if (widget.scrollController == null) {
      _internalScrollController = ScrollController();
    }
    widget.controller.attachCallbacks(
      onRefresh: _reset,
      onLoadMore: _handleLoadMoreRequested,
    );

    _handleRefresh();
  }

  @override
  void didUpdateWidget(covariant RefreshableList<T> oldWidget) {
    super.didUpdateWidget(oldWidget);
    if (oldWidget.controller != widget.controller) {
      oldWidget.controller.detachCallbacks();
      widget.controller.attachCallbacks(
        onRefresh: _reset,
        onLoadMore: _handleLoadMoreRequested,
      );
    }

    if (oldWidget.scrollController != widget.scrollController) {
      if (oldWidget.scrollController == null) {
        _internalScrollController?.dispose();
      }
      _internalScrollController =
          widget.scrollController == null ? ScrollController() : null;
    }
  }

  @override
  void dispose() {
    widget.controller.detachCallbacks();
    _easyRefreshController.dispose();
    _internalScrollController?.dispose();
    super.dispose();
  }

  Future<void> _reset() async {
    if (_refreshing) return;
    setState(() {
      _items.clear();
    });
    await _handleRefresh();
  }

  Future<void> _handleRefresh() async {
    if (_refreshing) return;
    _refreshing = true;
    final targetPage = widget.initialPage;

    try {
      final response = await widget.fetchData(targetPage, widget.pageSize);
      if (!mounted) return;
      setState(() {
        _page = targetPage;
        _total = response.total;
        _items
          ..clear()
          ..addAll(response.data);
      });
      _easyRefreshController.finishRefresh();
      _easyRefreshController.resetFooter();
    } catch (error, stackTrace) {
      widget.onError?.call(error, stackTrace);
      _easyRefreshController.finishRefresh(IndicatorResult.fail);
    } finally {
      _refreshing = false;
    }
  }

  Future<void> _handleLoadMoreRequested() async {
    if (_loadingMore) return;
    if (!_hasMore) {
      _easyRefreshController.finishLoad(IndicatorResult.noMore);
      return;
    }

    _loadingMore = true;

    final nextPage = _page + 1;

    try {
      final response = await widget.fetchData(nextPage, widget.pageSize);
      if (!mounted) return;
      setState(() {
        _page = nextPage;
        _total = response.total;
        _items.addAll(response.data);
      });
      _easyRefreshController.finishLoad(
        _hasMore ? IndicatorResult.success : IndicatorResult.noMore,
      );
    } catch (error, stackTrace) {
      widget.onError?.call(error, stackTrace);
      _easyRefreshController.finishLoad(IndicatorResult.fail);
    } finally {
      _loadingMore = false;
    }
  }

  Widget _buildList() {
    if (_items.isEmpty) {
      if (_refreshing) {
        return widget.loadingWidget ??
            const Center(child: CircularProgressIndicator());
      }
      return widget.emptyWidget ?? const Center(child: Text('暂无数据'));
    }

    return ListView.builder(
      controller: _effectiveScrollController,
      itemCount: _items.length,
      itemBuilder: (context, index) =>
          widget.itemBuilder(_items[index]),
    );
  }

  @override
  Widget build(BuildContext context) {
    return EasyRefresh(
      controller: _easyRefreshController,
      onRefresh: _handleRefresh,
      onLoad: _handleLoadMoreRequested,
      header: widget.header ?? const ClassicHeader(
        armedText: '释放刷新',
        readyText: '正在加载...',
        processedText: '加载完成',
        processingText: '正在刷新...',
        messageText: '更新于 %T',
        failedText: '刷新失败',
        noMoreText: '没有更多数据',
        dragText: '拉动刷新',
      ),
      footer: widget.footer ?? const ClassicFooter(
        dragText: '上拉以加载',
        armedText: '释放准备加载',
        readyText: '正在加载...',
        processingText: '正在加载...',
        processedText: '加载成功',
        noMoreText: '没有更多数据',
        failedText: '加载失败',
        messageText: '最后更新于 %T',
      ),
      child: _buildList(),
    );
  }
}

